home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
cpp_libs
/
awe2-0_1.lha
/
awe2-0.1
/
Src
/
RCS
/
GenericKeyedHeap.cc,v
< prev
next >
Wrap
Text File
|
1988-10-12
|
6KB
|
299 lines
head 1.1;
access ;
symbols ;
locks grunwald:1.1; strict;
comment @@;
1.1
date 88.09.18.16.42.22; author grunwald; state Exp;
branches ;
next ;
desc
@@
1.1
log
@Initial revision
@
text
@#include "Awesime.h"
#include "stream.h"
//
// This defines a Pairing Heap structure for a pointer data type.
//
// See ``The Pairing Heap: A New Form of Self-Adjusting Heap''
// Fredman, Segdewick et al,
// Algorithmica (1986) 1:111-129
//
// In particular, this implements the pairing heap using the circular
// list.
//
//
const GENERIC2(HEAP_NAME,Index) GENERIC2(HEAP_NAME,Null) = HEAP_INDEX_NULL;
#define NIL GENERIC2(HEAP_NAME,Null)
#define INDEX GENERIC2(HEAP_NAME,Index)
#define KEY GENERIC2(HEAP_NAME,Key)
#define ITEM GENERIC2(HEAP_NAME,Item)
static const char *GENERIC2(HEAP_NAME,Name) = GENERIC_STRING(HEAP_NAME) ;
HEAP_NAME::HEAP_NAME(int length, bool xdebug)
: (xdebug)
{
freelist = NIL;
allocatedSize = 0;
root = NIL;
elements = 0;
makeRoom(length);
}
void
HEAP_NAME::makeRoom(int atLeast)
{
//
// Out of free space?
//
if (freelist == NIL) {
//
// Is there existing storage?
//
if (allocatedSize > 0) {
#ifdef _CPPTWO_
#pragma linkage C
#endif /*_CPPTWO_*/
extern bcopy(void *, void *, int);
#ifdef _CPPTWO_
#pragma linkage
#endif /*_CPPTWO_*/
//
// Get new storage, copy over existing data & delete old storage
//
INDEX newSize = (allocatedSize * 3) / 2;
GENERIC2(HEAP_NAME,Record) *newStorage = new GENERIC2(HEAP_NAME,Record)[newSize];
char *newValid = new char[newSize];
if (newStorage == 0 || newValid == 0) {
cerr << "[" << GENERIC2(HEAP_NAME,Name) << "::makeRoom] Out of storage space\n";
exit(1);
}
bcopy(storage, newStorage, allocatedSize * sizeof(GENERIC2(HEAP_NAME,Record)));
bcopy(pValid, newValid, allocatedSize * sizeof(char));
delete storage;
delete pValid;
storage = newStorage;
pValid = newValid;
//
// Chain the new stuff into the free list
//
for (int i = allocatedSize; i < newSize; i++) {
storage[i].sibling = i+1;
pValid[i] = 0;
}
storage[newSize-1].sibling = NIL;
freelist = allocatedSize;
allocatedSize = newSize;
} else {
//
// No existing space
//
if (atLeast <= 8) {
allocatedSize = 8;
} else {
allocatedSize = atLeast;
}
storage = new GENERIC2(HEAP_NAME,Record)[allocatedSize];
pValid = new char[allocatedSize];
if (storage == 0) {
cerr << "[" << GENERIC2(HEAP_NAME,Name) << "::getCell] Out of storage\n";
exit(1);
}
for (int i = 0; i < allocatedSize; i++) {
storage[i].sibling = i+1;
pValid[i] = 0;
}
storage[allocatedSize-1].sibling = NIL;
freelist = 0;
}
}
}
//
// makeChild takes two nodes and makes one the child of the other
// and returns the index of the new parent.
//
// We play fast and loose with the siblings field of a & b, although
// we maintain the siblings of the children.
//
INDEX
HEAP_NAME::makeChild(INDEX a, INDEX b)
{
INDEX parent;
INDEX child;
if (storage[a].key <= storage[b].key) {
parent = a; child = b;
} else {
parent = b; child = a;
}
//
// If the new parent has no children, simply add the new child.
// We assume that the child and the parent dont care about
// their *sibling* nodes
//
INDEX popsKid = storage[parent].children;
if (popsKid == NIL) {
storage[parent].children = child;
storage[child].sibling = child;
} else {
INDEX temp = storage[popsKid].sibling;
storage[popsKid].sibling = child;
storage[child].sibling = temp;
storage[parent].children = child;
}
return(parent);
}
void
HEAP_NAME::add(KEY *key, ITEM *item)
{
INDEX cell = getCell();
storage[cell].key = *key;
storage[cell].item = *item;
storage[cell].children = NIL;
storage[cell].sibling = NIL;
if (root == NIL) {
root = cell;
} else {
//
// Make cell a child of root. Root may have no kids.
//
root = makeChild(root,cell);
}
}
//
// Item remove is the most complicated routine.
//
// We remove the root (should there be one) and then select a new
// root. The siblings of the root are in a cicular list. We continue
// to pair elements in this list until there is a single element.
// This element will be the new root.
bool
HEAP_NAME::remove(KEY *key, ITEM *removed)
{
bool valid = FALSE;
do {
if (root == NIL || elements <= 0) {
return(0);
}
*key = storage[root].key;
*removed = storage[root].item;
valid = pValid[root];
INDEX child = storage[root].children;
returnCell(root);
if (child == NIL) {
root = NIL;
} else {
while(storage[child].sibling != child) {
//
// We have at least two kids, but we may only have
// two kids. So, oneChild != child, but it is possible
// that twoChild == child.
//
INDEX oneChild = storage[child].sibling;
INDEX twoChild = storage[oneChild].sibling;
//
// Remove the two from the sibling list
//
storage[child].sibling = storage[twoChild].sibling;
storage[oneChild].sibling = NIL;
storage[twoChild].sibling = NIL;
INDEX bestChild = makeChild(oneChild, twoChild);
if (twoChild == child) {
//
// We have reduced the two to one, so we'll be exiting.
//
child = bestChild;
storage[child].sibling = child;
} else {
//
// We've removed two siblings, now we need to insert
// the better of the two
//
storage[bestChild].sibling = storage[child].sibling;
storage[child].sibling = bestChild;
child = storage[bestChild].sibling;
}
}
root = child;
}
} while ( !valid );
return(1);
}
bool
HEAP_NAME::doStart(INDEX &index)
{
for (index = 0; index < allocatedSize; index++) {
if (pValid[index]) {
return(TRUE);
}
}
return(FALSE);
}
bool
HEAP_NAME::doDelete(INDEX &index)
{
if (pValid[index]) {
pValid[index] = FALSE;
elements--;
return(TRUE);
} else {
return( FALSE );
}
}
bool
HEAP_NAME::doNext(INDEX& index)
{
//
// If they are moving on to the next element,
// they are sitting on the current on. So, move to the next
// and then look for a valid one.
//
for (index++; index < allocatedSize; index++) {
if (pValid[index]) {
return(TRUE);
}
}
return(FALSE);
}
void
HEAP_NAME::doDone()
{
//
// Do nothing.
//
}
@